﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;


namespace ColorTransform
{
    unsafe public class FastBitmap
    {
        private struct PixelData
        {
            public byte blue;
            public byte green;
            public byte red;
            public byte alpha;

            public override string ToString()
            {
                return "(" + alpha.ToString() + ", " + red.ToString() + ", " + green.ToString() + ", " + blue.ToString() + ")";
            }
        }

        private Bitmap workingBitmap = null;
        private int width = 0;
        private BitmapData bitmapData = null;
        private Byte* pBase = null;

        public FastBitmap(Bitmap inputBitmap)
        {
            workingBitmap = inputBitmap;
        }

        public void LockImage()
        {
            Rectangle bounds = new Rectangle(Point.Empty, workingBitmap.Size);

            width = (int)(bounds.Width * sizeof(PixelData));
            if (width % 4 != 0) width = 4 * (width / 4 + 1);

            //Lock Image
            bitmapData = workingBitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            pBase = (Byte*)bitmapData.Scan0.ToPointer();
        }

        private PixelData* pixelData = null;

        public Color GetPixel(int x, int y)
        {
            pixelData = (PixelData*)(pBase + y * width + x * sizeof(PixelData));
            return Color.FromArgb(pixelData->alpha, pixelData->red, pixelData->green, pixelData->blue);
        }

        public Color GetPixelNext()
        {
            pixelData++;
            return Color.FromArgb(pixelData->alpha, pixelData->red, pixelData->green, pixelData->blue);
        }

        public void SetPixel(int x, int y, Color color)
        {
            PixelData* data = (PixelData*)(pBase + y * width + x * sizeof(PixelData));
            data->alpha = color.A;
            data->red = color.R;
            data->green = color.G;
            data->blue = color.B;
        }

        public void UnlockImage()
        {
            workingBitmap.UnlockBits(bitmapData);
            bitmapData = null;
            pBase = null;
        }

        public static Image SetColor1(Image image, Color color)
        {
            Bitmap bmp = new Bitmap(image);
            int width = bmp.Width;
            int height = bmp.Height;


            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    Color realColor = bmp.GetPixel(i, j);
                    Color newColor = Color.FromArgb(realColor.A, color.R, color.G, color.B);
                    bmp.SetPixel(i, j, newColor);
                }
            }
            return bmp;
        }

        public static Image SetColor2(Image image, Color color)
        {
            Bitmap bmp1 = new Bitmap(image);

            FastBitmap bmp = new FastBitmap(bmp1);
            int width = bmp1.Width;
            int height = bmp1.Height;

            bmp.LockImage();
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    Color realColor = bmp.GetPixel(i, j);
                    Color newColor = Color.FromArgb(realColor.A, color.R, color.G, color.B);
                    bmp.SetPixel(i, j, newColor);
                }
            }
            bmp.UnlockImage();
            return bmp1;
        }

        public static Image SetColor4(Image image, Color color)
        {
            Bitmap bmp1 = new Bitmap(image.Width, image.Height);

            using (Graphics g = Graphics.FromImage(bmp1))
            {
                int width = bmp1.Width;
                int height = bmp1.Height;

                ImageAttributes attrs = new ImageAttributes();

                float r1 = color.R / 255f;
                float g1 = color.G / 255f;
                float b1 = color.B / 255f;


                float[][] mtrxValues = new float[][]
                {
                    new float[]  {0,  0,  0,  0,  0},
                    new float[]  {0,  0,  0,  0,  0},
                    new float[]  {0,  0,  0,  0,  0},
                    new float[]  {0,  0,  0,  1,  0},
                    new float[]  {r1,  g1,  b1,  0,  1}
                };
                ColorMatrix mtrx = new ColorMatrix(mtrxValues);

                Rectangle rect = new Rectangle(0, 0, width, height);
                attrs.SetColorMatrix(mtrx);
                g.DrawImage(image, rect, 0, 0, width, height, GraphicsUnit.Pixel, attrs);
                g.Flush();
            }
            return bmp1;
        }
    }
}

